﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ProgramMain.Database;
using ProgramMain.Database.SimpleOpticNetDBTableAdapters;
using ProgramMain.Google;

namespace ProgramMain.Layers
{
    public class VertexNode : IGoogleTreeNode
    {
        private SimpleOpticNetDB.VertexesRow _Row;

        public GoogleTreeTypes NodeType
        {
            get { return GoogleTreeTypes.Point; }
        }

        public Coordinate Coordinate
        {
            get { return new Coordinate(_Row.Longitude, _Row.Latitude); }
        }

        public CoordinateRectangle Rectangle
        {
            get { throw new NotImplementedException(); }
        }

        public int RowID
        {
            get { return _Row.ID; }
        }

        internal VertexNode(SimpleOpticNetDB.VertexesRow row)
        {
            _Row = row;    
        }

        public DataRow Row
        {
            get { return _Row; }
        }
    }

    public class VertexTree : GoogleTree<VertexNode>
    {
        public SimpleOpticNetDB.VertexesDataTable vertexDBRows { get; private set;}

        public VertexTree()
            : base(LevelPowerTypes.Ultra, LevelPowerTypes.Extra, LevelPowerTypes.Medium, LevelPowerTypes.Low)
        {
        }

        public void Insert(SimpleOpticNetDB.VertexesRow row)
        {
            base.Insert(new VertexNode(row));
        }

        public void Delete(SimpleOpticNetDB.VertexesRow row)
        {
            base.Delete(new VertexNode(row));
        }

        public void LoadData()
        {
            Clear();

            VertexesTableAdapter adapter = new VertexesTableAdapter();
            adapter.ClearBeforeFill = true;
            adapter.SelectCommandTimeout = Properties.Settings.Default.LongQueryTimeout;

            vertexDBRows = adapter.GetData(null, null, null, null, null, null, null, null, null);

            Parallel.ForEach(vertexDBRows.Cast<SimpleOpticNetDB.VertexesRow>(), Insert);
        }

        public void MergeData(SimpleOpticNetDB.VertexesDataTable vertexes)
        {
            if (vertexDBRows == null) return;

            vertexDBRows.Merge(vertexes, false, MissingSchemaAction.Error);

            Parallel.ForEach(vertexes.Cast<SimpleOpticNetDB.VertexesRow>(), delegate(SimpleOpticNetDB.VertexesRow row)
            {
                SimpleOpticNetDB.VertexesRow newRow = vertexDBRows.FindByID(row.ID);
                Insert(newRow);
            });
        }

        public bool RemoveVertex(int ObjectID)
        {
            SimpleOpticNetDB.VertexesRow row = (vertexDBRows == null) ? null : vertexDBRows.FindByID(ObjectID);
            if (row != null)
            {
                Delete(row);

                vertexDBRows.Rows.Remove(row);
                
                return true;
            }
            return false;
        }

        public SimpleOpticNetDB.VertexesRow FindVertex(int ObjectID)
        {
            if (vertexDBRows == null) return null;

            SimpleOpticNetDB.VertexesRow row = vertexDBRows.FindByID(ObjectID);
            if (row != null)
            {
                SimpleOpticNetDB.VertexesDataTable dt = (SimpleOpticNetDB.VertexesDataTable)vertexDBRows.Clone();
                dt.ImportRow(row);
                return (SimpleOpticNetDB.VertexesRow)dt.Rows[0];
            }
            return null;
        }
    }
}
